/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package Control;

import Control.exceptions.NonexistentEntityException;
import Control.exceptions.PreexistingEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import Entidades.Estadia;
import Entidades.Factura;
import Entidades.ResponsablePago;
import Entidades.Pasajero;
import Entidades.NotaCredito;
import java.util.ArrayList;
import java.util.List;
import Entidades.Pago;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author USUARIO
 */
public class FacturaJpaController implements Serializable {

    public FacturaJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Factura factura) throws PreexistingEntityException, Exception {
        if (factura.getNotaCreditoList() == null) {
            factura.setNotaCreditoList(new ArrayList<NotaCredito>());
        }
        if (factura.getPagoList() == null) {
            factura.setPagoList(new ArrayList<Pago>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Estadia idEstadia = factura.getIdEstadia();
            if (idEstadia != null) {
                idEstadia = em.getReference(idEstadia.getClass(), idEstadia.getIdEstadia());
                factura.setIdEstadia(idEstadia);
            }
            ResponsablePago responsablePago = factura.getResponsablePago();
            if (responsablePago != null) {
                responsablePago = em.getReference(responsablePago.getClass(), responsablePago.getCuit());
                factura.setResponsablePago(responsablePago);
            }
            Pasajero idPasajero = factura.getIdPasajero();
            if (idPasajero != null) {
                idPasajero = em.getReference(idPasajero.getClass(), idPasajero.getIdPasajero());
                factura.setIdPasajero(idPasajero);
            }
            List<NotaCredito> attachedNotaCreditoList = new ArrayList<NotaCredito>();
            for (NotaCredito notaCreditoListNotaCreditoToAttach : factura.getNotaCreditoList()) {
                notaCreditoListNotaCreditoToAttach = em.getReference(notaCreditoListNotaCreditoToAttach.getClass(), notaCreditoListNotaCreditoToAttach.getNroNota());
                attachedNotaCreditoList.add(notaCreditoListNotaCreditoToAttach);
            }
            factura.setNotaCreditoList(attachedNotaCreditoList);
            List<Pago> attachedPagoList = new ArrayList<Pago>();
            for (Pago pagoListPagoToAttach : factura.getPagoList()) {
                pagoListPagoToAttach = em.getReference(pagoListPagoToAttach.getClass(), pagoListPagoToAttach.getNroTransaccion());
                attachedPagoList.add(pagoListPagoToAttach);
            }
            factura.setPagoList(attachedPagoList);
            em.persist(factura);
            if (idEstadia != null) {
                idEstadia.getFacturaList().add(factura);
                idEstadia = em.merge(idEstadia);
            }
            if (responsablePago != null) {
                responsablePago.getFacturaList().add(factura);
                responsablePago = em.merge(responsablePago);
            }
            if (idPasajero != null) {
                idPasajero.getFacturaList().add(factura);
                idPasajero = em.merge(idPasajero);
            }
            for (NotaCredito notaCreditoListNotaCredito : factura.getNotaCreditoList()) {
                Factura oldNroFacturaOfNotaCreditoListNotaCredito = notaCreditoListNotaCredito.getNroFactura();
                notaCreditoListNotaCredito.setNroFactura(factura);
                notaCreditoListNotaCredito = em.merge(notaCreditoListNotaCredito);
                if (oldNroFacturaOfNotaCreditoListNotaCredito != null) {
                    oldNroFacturaOfNotaCreditoListNotaCredito.getNotaCreditoList().remove(notaCreditoListNotaCredito);
                    oldNroFacturaOfNotaCreditoListNotaCredito = em.merge(oldNroFacturaOfNotaCreditoListNotaCredito);
                }
            }
            for (Pago pagoListPago : factura.getPagoList()) {
                Factura oldFacturaOfPagoListPago = pagoListPago.getFactura();
                pagoListPago.setFactura(factura);
                pagoListPago = em.merge(pagoListPago);
                if (oldFacturaOfPagoListPago != null) {
                    oldFacturaOfPagoListPago.getPagoList().remove(pagoListPago);
                    oldFacturaOfPagoListPago = em.merge(oldFacturaOfPagoListPago);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findFactura(factura.getNroFactura()) != null) {
                throw new PreexistingEntityException("Factura " + factura + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Factura factura) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Factura persistentFactura = em.find(Factura.class, factura.getNroFactura());
            Estadia idEstadiaOld = persistentFactura.getIdEstadia();
            Estadia idEstadiaNew = factura.getIdEstadia();
            ResponsablePago responsablePagoOld = persistentFactura.getResponsablePago();
            ResponsablePago responsablePagoNew = factura.getResponsablePago();
            Pasajero idPasajeroOld = persistentFactura.getIdPasajero();
            Pasajero idPasajeroNew = factura.getIdPasajero();
            List<NotaCredito> notaCreditoListOld = persistentFactura.getNotaCreditoList();
            List<NotaCredito> notaCreditoListNew = factura.getNotaCreditoList();
            List<Pago> pagoListOld = persistentFactura.getPagoList();
            List<Pago> pagoListNew = factura.getPagoList();
            if (idEstadiaNew != null) {
                idEstadiaNew = em.getReference(idEstadiaNew.getClass(), idEstadiaNew.getIdEstadia());
                factura.setIdEstadia(idEstadiaNew);
            }
            if (responsablePagoNew != null) {
                responsablePagoNew = em.getReference(responsablePagoNew.getClass(), responsablePagoNew.getCuit());
                factura.setResponsablePago(responsablePagoNew);
            }
            if (idPasajeroNew != null) {
                idPasajeroNew = em.getReference(idPasajeroNew.getClass(), idPasajeroNew.getIdPasajero());
                factura.setIdPasajero(idPasajeroNew);
            }
            List<NotaCredito> attachedNotaCreditoListNew = new ArrayList<NotaCredito>();
            for (NotaCredito notaCreditoListNewNotaCreditoToAttach : notaCreditoListNew) {
                notaCreditoListNewNotaCreditoToAttach = em.getReference(notaCreditoListNewNotaCreditoToAttach.getClass(), notaCreditoListNewNotaCreditoToAttach.getNroNota());
                attachedNotaCreditoListNew.add(notaCreditoListNewNotaCreditoToAttach);
            }
            notaCreditoListNew = attachedNotaCreditoListNew;
            factura.setNotaCreditoList(notaCreditoListNew);
            List<Pago> attachedPagoListNew = new ArrayList<Pago>();
            for (Pago pagoListNewPagoToAttach : pagoListNew) {
                pagoListNewPagoToAttach = em.getReference(pagoListNewPagoToAttach.getClass(), pagoListNewPagoToAttach.getNroTransaccion());
                attachedPagoListNew.add(pagoListNewPagoToAttach);
            }
            pagoListNew = attachedPagoListNew;
            factura.setPagoList(pagoListNew);
            factura = em.merge(factura);
            if (idEstadiaOld != null && !idEstadiaOld.equals(idEstadiaNew)) {
                idEstadiaOld.getFacturaList().remove(factura);
                idEstadiaOld = em.merge(idEstadiaOld);
            }
            if (idEstadiaNew != null && !idEstadiaNew.equals(idEstadiaOld)) {
                idEstadiaNew.getFacturaList().add(factura);
                idEstadiaNew = em.merge(idEstadiaNew);
            }
            if (responsablePagoOld != null && !responsablePagoOld.equals(responsablePagoNew)) {
                responsablePagoOld.getFacturaList().remove(factura);
                responsablePagoOld = em.merge(responsablePagoOld);
            }
            if (responsablePagoNew != null && !responsablePagoNew.equals(responsablePagoOld)) {
                responsablePagoNew.getFacturaList().add(factura);
                responsablePagoNew = em.merge(responsablePagoNew);
            }
            if (idPasajeroOld != null && !idPasajeroOld.equals(idPasajeroNew)) {
                idPasajeroOld.getFacturaList().remove(factura);
                idPasajeroOld = em.merge(idPasajeroOld);
            }
            if (idPasajeroNew != null && !idPasajeroNew.equals(idPasajeroOld)) {
                idPasajeroNew.getFacturaList().add(factura);
                idPasajeroNew = em.merge(idPasajeroNew);
            }
            for (NotaCredito notaCreditoListOldNotaCredito : notaCreditoListOld) {
                if (!notaCreditoListNew.contains(notaCreditoListOldNotaCredito)) {
                    notaCreditoListOldNotaCredito.setNroFactura(null);
                    notaCreditoListOldNotaCredito = em.merge(notaCreditoListOldNotaCredito);
                }
            }
            for (NotaCredito notaCreditoListNewNotaCredito : notaCreditoListNew) {
                if (!notaCreditoListOld.contains(notaCreditoListNewNotaCredito)) {
                    Factura oldNroFacturaOfNotaCreditoListNewNotaCredito = notaCreditoListNewNotaCredito.getNroFactura();
                    notaCreditoListNewNotaCredito.setNroFactura(factura);
                    notaCreditoListNewNotaCredito = em.merge(notaCreditoListNewNotaCredito);
                    if (oldNroFacturaOfNotaCreditoListNewNotaCredito != null && !oldNroFacturaOfNotaCreditoListNewNotaCredito.equals(factura)) {
                        oldNroFacturaOfNotaCreditoListNewNotaCredito.getNotaCreditoList().remove(notaCreditoListNewNotaCredito);
                        oldNroFacturaOfNotaCreditoListNewNotaCredito = em.merge(oldNroFacturaOfNotaCreditoListNewNotaCredito);
                    }
                }
            }
            for (Pago pagoListOldPago : pagoListOld) {
                if (!pagoListNew.contains(pagoListOldPago)) {
                    pagoListOldPago.setFactura(null);
                    pagoListOldPago = em.merge(pagoListOldPago);
                }
            }
            for (Pago pagoListNewPago : pagoListNew) {
                if (!pagoListOld.contains(pagoListNewPago)) {
                    Factura oldFacturaOfPagoListNewPago = pagoListNewPago.getFactura();
                    pagoListNewPago.setFactura(factura);
                    pagoListNewPago = em.merge(pagoListNewPago);
                    if (oldFacturaOfPagoListNewPago != null && !oldFacturaOfPagoListNewPago.equals(factura)) {
                        oldFacturaOfPagoListNewPago.getPagoList().remove(pagoListNewPago);
                        oldFacturaOfPagoListNewPago = em.merge(oldFacturaOfPagoListNewPago);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = factura.getNroFactura();
                if (findFactura(id) == null) {
                    throw new NonexistentEntityException("The factura with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Factura factura;
            try {
                factura = em.getReference(Factura.class, id);
                factura.getNroFactura();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The factura with id " + id + " no longer exists.", enfe);
            }
            Estadia idEstadia = factura.getIdEstadia();
            if (idEstadia != null) {
                idEstadia.getFacturaList().remove(factura);
                idEstadia = em.merge(idEstadia);
            }
            ResponsablePago responsablePago = factura.getResponsablePago();
            if (responsablePago != null) {
                responsablePago.getFacturaList().remove(factura);
                responsablePago = em.merge(responsablePago);
            }
            Pasajero idPasajero = factura.getIdPasajero();
            if (idPasajero != null) {
                idPasajero.getFacturaList().remove(factura);
                idPasajero = em.merge(idPasajero);
            }
            List<NotaCredito> notaCreditoList = factura.getNotaCreditoList();
            for (NotaCredito notaCreditoListNotaCredito : notaCreditoList) {
                notaCreditoListNotaCredito.setNroFactura(null);
                notaCreditoListNotaCredito = em.merge(notaCreditoListNotaCredito);
            }
            List<Pago> pagoList = factura.getPagoList();
            for (Pago pagoListPago : pagoList) {
                pagoListPago.setFactura(null);
                pagoListPago = em.merge(pagoListPago);
            }
            em.remove(factura);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Factura> findFacturaEntities() {
        return findFacturaEntities(true, -1, -1);
    }

    public List<Factura> findFacturaEntities(int maxResults, int firstResult) {
        return findFacturaEntities(false, maxResults, firstResult);
    }

    private List<Factura> findFacturaEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Factura.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Factura findFactura(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Factura.class, id);
        } finally {
            em.close();
        }
    }

    public int getFacturaCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Factura> rt = cq.from(Factura.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
